package com.stdz.counter.utils;

import com.stdz.counter.core.constant.*;
import com.stdz.counter.core.exception.ResultException;
import com.stdz.counter.entity.MeterInfo;
import com.stdz.counter.entity.MeterModbus;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.Map;

public class MeterHelper {

    private static transient Logger logger = LoggerFactory.getLogger(MeterHelper.class);

    public static MeterInfo createMeterInfo(Map map) throws ResultException {
        checkCreateBaseParams(map);
        int connectType = Integer.parseInt(map.get("connectType").toString());
        if (connectType != ConnectType.COM.getType()) {
            throw new ResultException("请选择连接方式");
        }
        String comPort = map.get("comPort").toString();
        if (StringUtils.isBlank("comPort")) {
            throw new ResultException("请绑定MODBUS接口");
        }
        if (comPort.indexOf("COM") < 0) {
            throw new ResultException("MODBUS接口参数错误");
        }
        int baudRate = 9600;
        String meterName = map.get("meterName").toString();
        if (StringUtils.isBlank(meterName)) {
            throw new ResultException("请输入设备名称");
        }
        int iMeterModel = Integer.parseInt(map.get("meterModel").toString());
        MeterModel meterModel = MeterModel.getMeterModel(iMeterModel);
        if (meterModel == null) {
            throw new ResultException("请选择设备型号");
        }
        int iDataMode = Integer.parseInt(map.get("dataMode").toString());
        DataMode dataMode = DataMode.getDataMode(iDataMode);
        if (dataMode == null) {
            throw new ResultException("第一排显示数据格式错误");
        }
        if (meterModel == MeterModel.CR76 && dataMode == DataMode.BCD) {
            throw new ResultException("第一排显示数据格式选择错误");
        }
        int modbusDeviceId = Integer.parseInt(map.get("modbusDeviceId").toString());
        if (modbusDeviceId < 1 || modbusDeviceId > 32) {
            throw new ResultException("请输入正确的仪表编号");
        }
        int iClearMode = Integer.parseInt(map.get("clearMode").toString());
        int iClearLoopType = 0;
        ClearMode clearMode = ClearMode.getClearMode(iClearMode);
        if (clearMode == null) {
            throw new ResultException("请选择正确的清零模式");
        }
        Date clearTime = new Date();
        if (clearMode != ClearMode.NO_CLEAR) {
            if (!map.containsKey("clearLoopType")) {
                throw new ResultException("请选择清零执行方式");
            }
            if (!map.containsKey("clearTime")) {
                throw new ResultException("请完成定时清零设定");
            }
            iClearLoopType = Integer.parseInt(map.get("clearLoopType").toString());
            ClearLoopType clearLoopType = ClearLoopType.getClearLoopType(iClearLoopType);
            if (clearLoopType == null) {
                throw new ResultException("请选择正确的清零执行方式");
            }
            String szClearTime = map.get("clearTime").toString();
            if (StringUtils.isBlank(szClearTime)) {
                throw new ResultException("请完成定时清零设定");
            }
            clearTime = null;
            clearTime = DateFormatUtil.stringFormatDate(szClearTime, DateFormatUtil.STRING_DATE_FORMAT);

            if (clearTime == null) {
                throw new ResultException("定时清零设定错误");
            }

        }
        int modbusPos = Integer.parseInt(map.get("modbusPos").toString());
        MeterInfo meterInfo = new MeterInfo();
        meterInfo.setConnectType(connectType);
        meterInfo.setComPort(comPort);
        meterInfo.setBaudRate(baudRate);
        meterInfo.setMeterName(meterName);
        meterInfo.setMeterModel(iMeterModel);
        meterInfo.setModbusDeviceId((byte) modbusDeviceId);
        meterInfo.setModbusPos(modbusPos);
        meterInfo.setClearTime(clearTime);
        meterInfo.setDataMode(iDataMode);
        meterInfo.setClearMode(iClearMode);
        meterInfo.setClearLoopType(iClearLoopType);
        meterInfo.setCreateTime(new Date());
//        int decimlDigit = ModbusHelper.readDecimalDigitDatas(comPort, meterModel.getDecimalDigitPos());
//        meterInfo.setDecimalDigit(decimlDigit);
//        if (map.containsKey("alarm1")) {
//            String alarm1 = map.get("alarm1").toString();
//            if (StringUtils.isNotBlank(alarm1)) {
//                boolean success = meterInfo.setDisplayAlarm1(alarm1);
//                if (!success) {
//                    throw new ResultException("AL1报警值设定错误");
//                }
//            }
//
//        }
//        if (map.containsKey("alarm2")) {
//            String alarm2 = map.get("alarm2").toString();
//            if (StringUtils.isNotBlank(alarm2)) {
//                boolean success = meterInfo.setDisplayAlarm2(alarm2);
//                if (!success) {
//                    throw new ResultException("AL2报警值设定错误");
//                }
//            }
//        }
//
//        if (map.containsKey("scaleRate")) {
//            String scaleRate = map.get("scaleRate").toString();
//            if (StringUtils.isNotBlank(scaleRate)) {
//                boolean success = meterInfo.setDisplayScaleRate(map.get("scaleRate").toString());
//                if (!success) {
//                    throw new ResultException("计数倍率设定错误");
//                }
//            }
//        }
        return meterInfo;
    }

    public static MeterInfo modMeterInfo(Map map, int decimalDigit) throws ResultException {
        checkModParams(map);
        int connectType = Integer.parseInt(map.get("connectType").toString());
        if (connectType != ConnectType.COM.getType()) {
            throw new ResultException("请选择连接方式");
        }
        String comPort = map.get("comPort").toString();
        if (StringUtils.isBlank("comPort")) {
            throw new ResultException("请绑定MODBUS接口");
        }
        if (comPort.indexOf("COM") < 0) {
            throw new ResultException("MODBUS接口参数错误");
        }
        int baudRate = 9600;
        String meterName = map.get("meterName").toString();
        if (StringUtils.isBlank(meterName)) {
            throw new ResultException("请输入设备名称");
        }
        int iMeterModel = Integer.parseInt(map.get("meterModel").toString());
        MeterModel meterModel = MeterModel.getMeterModel(iMeterModel);
        if (meterModel == null) {
            throw new ResultException("请选择设备型号");
        }
        int iDataMode = Integer.parseInt(map.get("dataMode").toString());
        DataMode dataMode = DataMode.getDataMode(iDataMode);
        if (dataMode == null) {
            throw new ResultException("第一排显示数据格式错误");
        }
        if (meterModel == MeterModel.CR76 && dataMode == DataMode.BCD) {
            throw new ResultException("第一排显示数据格式选择错误");
        }
        int modbusDeviceId = Integer.parseInt(map.get("modbusDeviceId").toString());
        if (modbusDeviceId < 1 || modbusDeviceId > 32) {
            throw new ResultException("请输入正确的仪表编号");
        }
        int iClearMode = Integer.parseInt(map.get("clearMode").toString());
        int iClearLoopType = 0;
        ClearMode clearMode = ClearMode.getClearMode(iClearMode);
        if (clearMode == null) {
            throw new ResultException("请选择正确的清零模式");
        }
        Date clearTime = new Date();
        if (clearMode != ClearMode.NO_CLEAR) {
            if (!map.containsKey("clearLoopType")) {
                throw new ResultException("请选择清零执行方式");
            }
            if (!map.containsKey("clearTime")) {
                throw new ResultException("请完成定时清零设定");
            }
            iClearLoopType = Integer.parseInt(map.get("clearLoopType").toString());
            ClearLoopType clearLoopType = ClearLoopType.getClearLoopType(iClearLoopType);
            if (clearLoopType == null) {
                throw new ResultException("请选择正确的清零执行方式");
            }
            String szClearTime = map.get("clearTime").toString();
            if (StringUtils.isBlank(szClearTime)) {
                throw new ResultException("请完成定时清零设定");
            }
            clearTime = null;
            clearTime = DateFormatUtil.stringFormatDate(szClearTime, DateFormatUtil.STRING_DATE_FORMAT);

            if (clearTime == null) {
                throw new ResultException("定时清零设定错误");
            }

        }
        int modbusPos = Integer.parseInt(map.get("modbusPos").toString());
        int meterId = Integer.parseInt(map.get("meterId").toString());
        MeterInfo meterInfo = new MeterInfo();
        meterInfo.setMeterId(meterId);
        meterInfo.setConnectType(connectType);
        meterInfo.setDecimalDigit(decimalDigit);
        meterInfo.setComPort(comPort);
        meterInfo.setBaudRate(baudRate);
        meterInfo.setMeterName(meterName);
        meterInfo.setMeterModel(iMeterModel);
        meterInfo.setModbusDeviceId((byte) modbusDeviceId);
        meterInfo.setModbusPos(modbusPos);
        meterInfo.setClearTime(clearTime);
        meterInfo.setDataMode(iDataMode);
        meterInfo.setClearMode(iClearMode);
        meterInfo.setClearLoopType(iClearLoopType);
        if (map.containsKey("alarm1")) {
            String alarm1 = map.get("alarm1").toString();
            if (StringUtils.isNotBlank(alarm1)) {
                boolean success = meterInfo.setDisplayAlarm1(alarm1);
                if (!success) {
                    throw new ResultException("AL1报警值设定错误");
                }
            }

        }
        if (map.containsKey("alarm2")) {
            String alarm2 = map.get("alarm2").toString();
            if (StringUtils.isNotBlank(alarm2)) {
                boolean success = meterInfo.setDisplayAlarm2(alarm2);
                if (!success) {
                    throw new ResultException("AL2报警值设定错误");
                }
            }
        }

        if (map.containsKey("scaleRate")) {
            String scaleRate = map.get("scaleRate").toString();
            if (StringUtils.isNotBlank(scaleRate)) {
                boolean success = meterInfo.setDisplayScaleRate(map.get("scaleRate").toString());
                if (!success) {
                    throw new ResultException("计数倍率设定错误");
                }
            }
        }
        return meterInfo;
    }

    private static void checkCreateBaseParams(Map map) throws ResultException {
        if (map == null) {
            throw new ResultException("请求参数为空");
        }
        if (!map.containsKey("connectType")) {
            throw new ResultException("请选择通讯接口");
        }
        if (!map.containsKey("comPort")) {
            throw new ResultException("请绑定MODBUS接口");
        }
        if (!map.containsKey("meterName")) {
            throw new ResultException("请输入设备名称");
        }

        if (!map.containsKey("meterModel")) {
            throw new ResultException("请选择设备型号");
        }
        if (!map.containsKey("modbusDeviceId")) {
            throw new ResultException("请输入仪表编号");
        }
        if (!map.containsKey("dataMode")) {
            throw new ResultException("请选择第一排显示数据格式");
        }
        if (!map.containsKey("modbusPos")) {
            throw new ResultException("请输入第一排显示值寄存器地址");
        }
        if (!map.containsKey("clearMode")) {
            throw new ResultException("请选择清零模式");
        }

    }

    private static void checkModParams(Map map) throws ResultException {
        if (map == null) {
            throw new ResultException("请求参数为空");
        }
        if (!map.containsKey("meterId")) {
            throw new ResultException("请求参数错误，请返回重试");
        }
        if (!map.containsKey("comPort")) {
            throw new ResultException("请绑定MODBUS接口");
        }
        if (!map.containsKey("meterName")) {
            throw new ResultException("请输入设备名称");
        }

        if (!map.containsKey("meterModel")) {
            throw new ResultException("请选择设备型号");
        }
        if (!map.containsKey("modbusDeviceId")) {
            throw new ResultException("请输入仪表编号");
        }
        if (!map.containsKey("dataMode")) {
            throw new ResultException("请选择第一排显示数据格式");
        }
        if (!map.containsKey("modbusPos")) {
            throw new ResultException("请输入第一排显示值寄存器地址");
        }
        if (!map.containsKey("clearMode")) {
            throw new ResultException("请选择清零模式");
        }

    }

    /**
     * 判断是否执行清零
     * @param meterInfo
     * @param currentTimeMillis
     * @return
     */
    public static boolean ifClearEnable(MeterInfo meterInfo, long currentTimeMillis) {
        ClearMode clearMode = ClearMode.getClearMode(meterInfo.getClearMode());
        if (clearMode == null || clearMode == ClearMode.NO_CLEAR) {
            return false;
        }
        ClearLoopType clearLoopType = ClearLoopType.getClearLoopType(meterInfo.getClearLoopType());
        if (clearLoopType == null) {
            return false;
        }
        Date clearTime = meterInfo.getClearTime();
        if (clearTime == null) {
            return false;
        }
        if (clearLoopType == ClearLoopType.SINGLE_OPERATE) {
            // 单清零
            Date lastClearTime = meterInfo.getLastClearTime();
            if (lastClearTime != null) {
                long spanTime = Math.abs(lastClearTime.getTime() - clearTime.getTime());
                if (spanTime < 5000L) {
                    return false;
                }
            }

        }
        long spanTime = currentTimeMillis - clearTime.getTime();
        if (spanTime > -3000 && spanTime <= clearLoopType.getClearOverTime()) { // 据清理时间不足3秒可以开始清理
            return true;
        }
        return false;
    }

    /**
     * 清零超时
     * @param meterInfo
     * @param currentTimeMillis
     * @return
     */
    public static boolean ifClearOverTime(MeterInfo meterInfo, long currentTimeMillis) {
        ClearMode clearMode = ClearMode.getClearMode(meterInfo.getClearMode());
        if (clearMode == null || clearMode == ClearMode.NO_CLEAR) {
            return false;
        }
        ClearLoopType clearLoopType = ClearLoopType.getClearLoopType(meterInfo.getClearLoopType());
        if (clearLoopType == null) {
            return false;
        }
        Date clearTime = meterInfo.getClearTime();
        if (clearTime == null) {
            return false;
        }
        long spanTime = currentTimeMillis - clearTime.getTime();
        if (spanTime > clearLoopType.getClearOverTime()) {
            return false;
        }
        return true;
    }
}
